package com.changpei.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.changpei.common.cache.CommentCache;
import com.changpei.common.cache.UserCache;
import com.changpei.common.result.enums.CommonCode;
import com.changpei.core.config.AliYunOssUtil;
import com.changpei.core.config.RabbitInfoConfig;
import com.changpei.core.dao.CommentMapper;
import com.changpei.core.pojo.Comment;
import com.changpei.core.service.CommentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>Title: Comment</p>
 * <p>Description: Comment业务层接口实现类</p>
 *
 * @author weibiao
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Autowired
    private UserCache userCache;

    @Autowired
    private CommentCache commentCache;

    @Autowired
    private RabbitInfoConfig rabbitInfoConfig;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private AliYunOssUtil aliYunOssUtil;

    /**
     * 锁对象
     */
    private final Lock lock = new ReentrantLock();

    @Override
    public Map<String, Object> comment(Map<String, Object> map) {

        Map<String, Object> result = new HashMap<>(2);
        result.put("result", true);
        result.put("msg", "操作成功");

        // 加锁
        lock.lock();
        try {
            String token = map.get("token").toString();
            String commentParam = map.get("comment").toString();
            Long userId = userCache.getUserId(token);
            Comment comment = JSONObject.parseObject(commentParam, Comment.class);
            comment.setUserId(userId);
            comment.setId(commentCache.getCommentSequenceId());
            comment.setCreateTime(new Date());
            JSONObject jsonObject = JSONObject
                    .parseObject(JSON.toJSONString(comment, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullNumberAsZero));

            boolean scanTextResult = aliYunOssUtil.scanText(comment.getContent());
            if (!scanTextResult) {
                result.put("result", false);
                result.put("msg", CommonCode.COMMENT_TEXT_ERROR.message());
                return result;
            }
            commentCache.comment(String.valueOf(comment.getContentId()), jsonObject);

            // 发送到rabbitMQ,通知es修改信息
            rabbitTemplate.convertAndSend(rabbitInfoConfig.getExchange().get("comment"),
                    rabbitInfoConfig.getRouting().get("comment"),
                    JSON.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue,
                            SerializerFeature.WriteNullNumberAsZero));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("用户评论异常:{}", e.getMessage());
            result.put("result", false);
            result.put("msg", "用户评论异常");
            return result;
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    @Override
    public JSONObject like(Map<String, Object> map) {

        JSONObject result = new JSONObject();
        result.put("like", false);
        result.put("praiseNum", 0);

        // 加锁
        lock.lock();

        try {
            String token = map.get("token").toString();
            Long commentId = Long.parseLong(map.get("commentId").toString());
            boolean like = commentCache.like(userCache.getUserId(token), commentId);
            if (like) {
                long praiseNum = commentCache.incrPraiseNum(commentId);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", commentId);
                jsonObject.put("praiseNum", praiseNum);
                // 添加返回数
                result.put("praiseNum", praiseNum);
                commentModify(jsonObject);
            }
            result.put("like", like);
            return result;
        } catch (Exception e) {
            log.error("用户评论点赞异常:{}", e.getMessage());
            return result;
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    @Override
    public JSONObject unlike(Map<String, Object> map) {
        JSONObject result = new JSONObject();
        result.put("like", false);
        result.put("praiseNum", 0);

        // 加锁
        lock.lock();

        try {
            String token = map.get("token").toString();
            Long commentId = Long.parseLong(map.get("commentId").toString());
            boolean like = commentCache.unlike(userCache.getUserId(token), commentId);
            if (!like) {
                long praiseNum = commentCache.derPraiseNum(commentId);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", commentId);
                jsonObject.put("praiseNum", praiseNum);
                // 添加返回数
                result.put("praiseNum", praiseNum);
                commentModify(jsonObject);
            }

            result.put("like", like);
            return result;
        } catch (Exception e) {
            log.error("用户取消评论点赞异常:{}", e.getMessage());
            return result;
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    @Override
    public boolean delete(Map<String, Object> map) {
        // 加锁
        lock.lock();
        try {
            Long contentId = Long.parseLong(map.get("contentId").toString());
            Long commentId = Long.parseLong(map.get("commentId").toString());
            Set<Long> ids = commentCache.del(contentId, commentId);
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("ids", ids);
            commentModify(jsonObject);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("用户删除评论异常:{}", e.getMessage());
            return false;
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

    private void commentModify(JSONObject jsonObject) {
        // 发送到rabbitMQ,通知es修改信息
        rabbitTemplate.convertAndSend(rabbitInfoConfig.getExchange().get("commentModify"),
                rabbitInfoConfig.getRouting().get("commentModify"),
                JSON.toJSONString(jsonObject, SerializerFeature.WriteMapNullValue,
                        SerializerFeature.WriteNullNumberAsZero));
    }

}
